// Learn TypeScript:
//  - https://docs.cocos.com/creator/manual/en/scripting/typescript.html
// Learn Attribute:
//  - https://docs.cocos.com/creator/manual/en/scripting/reference/attributes.html
// Learn life-cycle callbacks:
//  - https://docs.cocos.com/creator/manual/en/scripting/life-cycle-callbacks.html

export default class SodaEventSoda {
    static UPDATE_USER_DATA: string = "update_user_data"; //更新用户信息

    static USER_ADD_DATA: string = "user_add_data"; //用户请求积分

    static USER_ADD_INTEGRAL: string = "user_add_integral"; //用户增加本地积分

    static USER_EXCHANGE_SUCC: string = "user_exchange_succ"; //用户兑换积分成功

    static ERROR: string = "error"; //行为错误

    // 所有事件的监听器
    static es: EventsType = {};

    public static on(eventName: string, cb: Function, target: object) {
        if (!this.es[eventName]) {
            this.es[eventName] = [];
        }

        this.es[eventName].push({
            cb,
            once: false,
            target,
        });
    }

    public static once(eventName: string, cb: Function, target: object) {
        if (!this.es[eventName]) {
            this.es[eventName] = [];
        }

        this.es[eventName].push({
            cb,
            once: true,
            target,
        });
    }

    private static fire(eventName: string, params: any) {
        const listeners = this.es[eventName] || [];

        let l = listeners.length;

        for (let i = 0; i < l; i++) {
            const { cb, once, target } = listeners[i];
            let args = [eventName, params];
            cb.apply(target, args);

            if (once) {
                listeners.splice(i, 1);
                i--;
                l--;
            }
        }
    }

    public static off(eventName?: string, cb?: Function, target?: object) {
        // clean all
        if (eventName === undefined) {
            this.es = {};
        } else {
            if (cb === undefined) {
                // clean the eventName's listeners
                delete this.es[eventName];
            } else if (cb === null) {
                if (!target) {
                    return;
                }
                const listeners = this.es[eventName] || [];
                // clean the event and listener
                let l = listeners.length;
                for (let i = 0; i < l; i++) {
                    if (listeners[i].target === target) {
                        listeners.splice(i, 1);
                        i--;
                        l--;
                    }
                }
            } else {
                const listeners = this.es[eventName] || [];
                // clean the event and listener
                let l = listeners.length;
                for (let i = 0; i < l; i++) {
                    if (listeners[i].cb === cb && listeners[i].target === target) {
                        listeners.splice(i, 1);
                        i--;
                        l--;
                    }
                }
            }
        }
    }

    // cname of fire
    public static emit(eventName: string, params = null) {
        this.fire(eventName, params);
    }
}
export interface Listener {
    cb: Function;
    once: boolean;
    target: object;
}

export interface EventsType {
    [eventName: string]: Listener[];
}

